/* eslint-disable max-lines-per-function */
import React, {useState, useRef} from 'react';
// eslint-disable-next-line camelcase
import {unstable_batchedUpdates} from 'react-dom';
import {useRequest, useModel, Link} from 'umi';
import {notification} from 'antd';
import {SelectGroup} from 'Feitud';
// ahooks相关API请查阅https://ahooks.js.org/zh-CN/docs/getting-started
import {usePersistFn, useCreation, useMount, useBoolean} from 'ahooks';
// import {PageContainer} from '@ant-design/pro-layout';
import PageHeader from '@/components/PageHeader';
import AlertTable from '@/components/AlertTable';
import {convertSort} from '@/utils/utils';
import SearchForm from './SearchForm';
import {ADD_TYPE, EDIT_TYPE} from './EditForm';
import AsyncEditForm from './AsyncEditForm';
import {getList, saveItem, delItem} from './service';
import {getColumns} from './config';
import styles from './index.less';

const Crud = () => {
    const [sortInfo, setSortInfo] = useState({});
    const [filterInfo, setFilterInfo] = useState({});
    const [curRecord, setCurRecord] = useState<API.CurdItem | null>(null);
    const [formVisible, {setTrue, setFalse}] = useBoolean(false);
    // 存储当前的筛选条件
    const curParams = useRef({});
    // useRequest官方文档：https://ahooks.js.org/zh-CN/hooks/async
    // 筛选项接口
    const {filters, tablefilters, selectOptions} = useModel('filters');
    // 所有请求都通过useRequest，抽离data、loading和run。
    // 列表接口
    const {data: listRes, loading, run, refresh} = useRequest(getList, {
        manual: true,
        // 防抖设置，必须写
        debounceInterval: 500,
        // 在此处格式化接口返回的数据，处理成组件可以直接使用的数据格式，如果接口数据格式满足，则不需要
        formatResult(res) {
            // 注意容错处理
            const {code, data, pager} = res || {};
            if (code === 0) {
                return {
                    // 使用?.处理容错，避免低级错误
                    list: data?.list || [],
                    pager
                };
            }
            return {list: []};
        }
    }) || {};
    // 编辑接口
    const {loading: editLoading, run: editSubmit} = useRequest(saveItem, {
        manual: true,
        debounceInterval: 500,
        onSuccess() {
            setFalse();
            // 编辑完重新请求，自动使用上次请求的参数
            refresh();
        }
    }) || {};
    // 删除接口
    const {run: delSubmit} = useRequest(delItem, {
        manual: true,
        debounceInterval: 500,
        onSuccess() {
            notification.success({message: '删除成功'});
            // 删除完重新请求，自动使用上次请求的参数
            refresh();
        }
    }) || {};
    // 组件挂载
    useMount(() => {
        // 注意容错处理
        if (typeof run === 'function') {
            run({});
        }
    });
    // 函数均用usePersistFn或者useCallbback包裹，usePersistFn可以理解为没有依赖的useCallback简化，保证函数地址变
    // 搜索
    const handleSubmit = usePersistFn(params => {
        curParams.current = {
            ...curParams.current,
            ...params
        };
        if (typeof run === 'function') {
            run(curParams.current);
            unstable_batchedUpdates(() => {
                setSortInfo({});
                setFilterInfo({});
            });
        }
    });
    // 重置
    const handleReset = usePersistFn(() => {
        if (typeof run === 'function') {
            curParams.current = {};
            run({});
            unstable_batchedUpdates(() => {
                setSortInfo({});
                setFilterInfo({});
            });
        }
    });
    // 弹出编辑框
    const showEdit = usePersistFn(record => {
        unstable_batchedUpdates(() => {
            setTrue();
            setCurRecord(record);
        });
    });
    // 弹出新增框
    const showAdd = usePersistFn(() => {
        unstable_batchedUpdates(() => {
            setTrue();
            setCurRecord(null);
        });
    });
    // 删除的回调
    const handleDel = usePersistFn(id => {
        if (typeof delSubmit === 'function') {
            delSubmit({id});
        }
    });

    // 这里使用useCreation代替useMemo，因为官方称useMemo记忆性可能不太好，依赖变化columns才会改变
    const columns = useCreation(() =>
        getColumns(sortInfo, filterInfo, tablefilters, showEdit, handleDel),
    [sortInfo, filterInfo, tablefilters]);

    const SelectGroupData = useCreation(() => [
        {
            key: 'grade',
            name: 'grade',
            multiple: true,
            label: '年级',
            options: selectOptions?.gradeList || [],
        },
        {
            key: 'department',
            name: 'department',
            label: '学部',
            options: selectOptions?.departmentList || [],
        },
        {
            key: 'subject',
            name: 'subject',
            multiple: true,
            label: '学科',
            options: selectOptions?.subjectList || [],
        },
    ], [selectOptions]);

    // usePersistFn 是 持久化 function 的 Hook
    // 在某些场景中，你可能会需要用 useCallback 记住一个回调，但由于内部函数必须经常重新创建，
    // 记忆效果不是很好，导致子组件重复 render。对于超级复杂的子组件，重新渲染会对性能造成影响。
    // 通过 usePersistFn，可以保证函数地址永远不会变化
    const handelTableChange = usePersistFn((pager, filters, sorter) => {
        const sortedInfo = convertSort(sorter);
        if (typeof run === 'function') {
            run({
                ...curParams.current,
                // 展开运算符要注意容错
                ...(filters || {}),
                ...sortedInfo,
                pager
            });
        }
        // unstable_batchedUpdates 合并多个setState一次执行
        unstable_batchedUpdates(() => {
            setSortInfo(sorter);
            setFilterInfo(filters);
        });
    });
    // useCreation 是 useMemo 或 useRef 的替代品。
    // 因为 useMemo 不能保证被 memo 的值一定不会被重计算，而 useCreation 可以保证这一点
    const oprations = useCreation(() => (
        <Link
            // type="link"
            // onClick={showAdd}
            // style={{padding: 0, lineHeight: 'inherit', height: 'auto'}}
            to="/crud/edit/0"
        >
            新增
        </Link>
    ), []);
    // 从页面结构上我们拆分成三个组件，1、搜索表单，2、表格，3、弹出的表单（异步加载）
    // PageContainer属性请查阅https://procomponents.ant.design/components/layout#pagecontainer
    return (
        <PageHeader>
            <div className={styles.card}>
                <SearchForm
                    onFinish={handleSubmit}
                    onReset={handleReset}
                    // 表单的查询按钮也要添加loading或者disabled，防止卡顿请求多次
                    loading={loading}
                />
            </div>
            <div className={`${styles.mt10} ${styles.card}`}>
                <SelectGroup
                    // @ts-ignore
                    dataSource={SelectGroupData}
                    onChange={handleSubmit}
                />
            </div>
            <div className={`${styles.mt10} ${styles.card}`}>
                <AlertTable
                    // 表格添加loading
                    loading={loading}
                    // 使用?.处理容错，避免低级错误
                    dataSource={listRes?.list || []}
                    // @ts-ignore
                    columns={columns}
                    rowKey="id"
                    scroll={{x: 1600}}
                    onChange={handelTableChange}
                    pagination={listRes?.pager || {}}
                    oprations={oprations}
                />
            </div>
            <AsyncEditForm
                // @ts-ignore
                type={curRecord ? EDIT_TYPE : ADD_TYPE}
                visible={formVisible}
                onOk={editSubmit}
                onCancel={setFalse}
                // 表单按钮添加loading
                loading={editLoading}
                record={curRecord}
                departmentList={filters?.departmentList || []}
                gradeList={filters?.gradeList || []}
            />
        </PageHeader>
    );
};

export default Crud;
